#include "Shader.h"

#include "Runtime/Utils/FileSystem.h"

namespace Alice
{
    template VertexShader* Shader::GetOrCreateShaderFromShaderPath<VertexShader>(EMeshPass::Type inMeshPass,const char* inShaderPath);
    template PixelShader* Shader::GetOrCreateShaderFromShaderPath<PixelShader>(EMeshPass::Type inMeshPass,const char* inShaderPath);
    std::unordered_map<std::string,Shader*> Shader::mCachedShaders;
    Shader::Shader(EShaderFrequency inShaderFrequency, EMeshPass::Type inMeshPass)
        :mShaderFrequency(inShaderFrequency),mMeshPass(inMeshPass)
    {
        
    }
    void ShaderPipeline::SetShader(EShaderFrequency inShaderFrequency,Shader*inShader)
    {
        mShaders[inShaderFrequency]=inShader;
    }

    template <typename T>
    T* Shader::GetOrCreateShaderFromShaderPath(EMeshPass::Type inMeshPass,const char* inShaderPath)
    {
        const auto iter=mCachedShaders.find(inShaderPath);
        if(iter!=mCachedShaders.end())
        {
            return reinterpret_cast<T*>(iter->second);
        }
        T*shader=new T(inMeshPass,inShaderPath);
        mCachedShaders.insert(std::pair<std::string,Shader*>(inShaderPath,shader));
        return shader;
    }
    VertexShader::VertexShader(EMeshPass::Type inMeshPass, const char* inShaderPath)
        :Shader(EShaderFrequency::SF_Vertex,inMeshPass)
    {
        mShaderCode=new Data;
        FileSystem::LoadDataFromPath(inShaderPath,*mShaderCode);
        mCGIShader=CGICreateVertexShader(inShaderPath,mShaderCode->mData,mShaderCode->mDataLen);
    }
    PixelShader::PixelShader(EMeshPass::Type inMeshPass, const char* inShaderPath)
        :Shader(EShaderFrequency::SF_Pixel,inMeshPass)
    {
        mShaderCode=new Data;
        FileSystem::LoadDataFromPath(inShaderPath,*mShaderCode);
        mCGIShader=CGICreatePixelShader(inShaderPath,mShaderCode->mData,mShaderCode->mDataLen);
    }
    
    static std::vector<const FShaderTypeRegistration*>* GShaderTypeRegistrationInstances = nullptr;
    std::vector<const FShaderTypeRegistration*>& FShaderTypeRegistration::GetInstances()
    {
        if(GShaderTypeRegistrationInstances==nullptr)
        {
            GShaderTypeRegistrationInstances=new std::vector<const FShaderTypeRegistration*>;
        }
        return *GShaderTypeRegistrationInstances;
    }

    void FShaderMapBase::InitResource()
    {
        
    }

    void FShaderMapBase::FinalizeContent()
    {
        InitResource();
    }
    void FMaterialShaderMap::Compile(MaterialShared* inMaterial)
    {
        
    }
    TBasePassVS::ShaderMetaType& TBasePassVS::GetStaticType()
    {
        static TBasePassVS::ShaderMetaType staticType(TEXT("Res/test.vs"));
        return staticType;
    }
    FShaderTypeRegistration TBasePassVS::ShaderTypeRegistration(&TBasePassVS::GetStaticType);
    TBasePassPS::ShaderMetaType& TBasePassPS::GetStaticType()
    {
        static TBasePassPS::ShaderMetaType staticType(TEXT("Res/test.fs"));
        return staticType;
    }
    FShaderTypeRegistration TBasePassPS::ShaderTypeRegistration(&TBasePassPS::GetStaticType);
}
